﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using NewLife.Collections;

namespace XCode
{
    /// <summary>实体列表视图</summary>
    /// <typeparam name="T">实体类</typeparam>
    partial class EntityListView<T> : ListBase<T>, ITypedList, IBindingList, IBindingListView, ICancelAddNew where T : IEntity
    {
        #region 重载
        /// <summary>初始化</summary>
        public EntityListView()
        {
            // 使用实体列表作为内部列表，便于提供排序等功能
            InnerList = new EntityList<T>();
        }

        /// <summary>实体列表</summary>
        /// <param name="list"></param>
        public EntityListView(IList<T> list)
        {
            InnerList = list;
        }

        /// <summary>已重载。新增元素时，触发事件改变</summary>
        /// <param name="index"></param>
        /// <param name="value">数值</param>
        public override void Insert(Int32 index, T value)
        {
            base.Insert(index, value);

            OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
        }

        /// <summary>已重载。从列表中删除项时，同时从数据库中删除实体</summary>
        /// <param name="index"></param>
        public override void RemoveAt(Int32 index)
        {
            T entity = this[index];
            entity.Delete();

            base.RemoveAt(index);

            OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
        }
        #endregion

        #region ITypedList接口
        PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
        {
            var type = typeof(T);
            // 调用TypeDescriptor获取属性
            var pdc = TypeDescriptor.GetProperties(type);
            if (pdc == null || pdc.Count <= 0) return pdc;

            return EntityBase.Fix(type, pdc);
        }

        String ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return null; }
        #endregion

        #region IBindingList接口
        #region 属性
        Boolean _AllowEdit = true;
        /// <summary>获取是否可更新列表中的项。</summary>
        public Boolean AllowEdit
        {
            get { return _AllowEdit; }
            set { if (_AllowEdit != value) { _AllowEdit = value; OnListChanged(ResetEventArgs); }; }
        }

        Boolean _AllowNew = true;
        /// <summary>获取是否可以使用 System.ComponentModel.IBindingList.AddNew() 向列表中添加项。</summary>
        public Boolean AllowNew
        {
            get { return _AllowNew; }
            set { if (_AllowNew != value) { _AllowNew = value; OnListChanged(ResetEventArgs); }; }
        }

        Boolean _AllowRemove = true;
        /// <summary>获取是否可以使用 System.Collections.IList.Remove(System.Object) 或 System.Collections.IList.RemoveAt(System.Int32)从列表中移除项。</summary>
        public Boolean AllowRemove
        {
            get { return _AllowRemove; }
            set { if (_AllowRemove != value) { _AllowRemove = value; OnListChanged(ResetEventArgs); }; }
        }

        Boolean _IsSorted = false;
        /// <summary>获取是否对列表中的项进行排序。</summary>
        public Boolean IsSorted
        {
            get { return _IsSorted; }
            set { if (_IsSorted != value) { _IsSorted = value; OnListChanged(ResetEventArgs); }; }
        }

        ListSortDirection _SortDirection;
        /// <summary>获取排序的方向。</summary>
        public ListSortDirection SortDirection
        {
            get { return _SortDirection; }
            set { if (_SortDirection != value) { _SortDirection = value; OnListChanged(ResetEventArgs); }; }
        }

        PropertyDescriptor _SortProperty;
        /// <summary>获取正在用于排序的 System.ComponentModel.PropertyDescriptor。</summary>
        public PropertyDescriptor SortProperty
        {
            get { return _SortProperty; }
            set { if (_SortProperty != value) { _SortProperty = value; OnListChanged(ResetEventArgs); }; }
        }

        Boolean IBindingList.SupportsChangeNotification { get { return true; } }

        Boolean IBindingList.SupportsSearching { get { return true; } }

        Boolean IBindingList.SupportsSorting { get { return true; } }
        #endregion

        #region 事件
        /// <summary>列表改变事件</summary>
        public event ListChangedEventHandler ListChanged;

        static ListChangedEventArgs ResetEventArgs = new ListChangedEventArgs(ListChangedType.Reset, -1);

        void OnListChanged(ListChangedEventArgs e)
        {
            if (ListChanged != null) ListChanged(this, e);
        }
        #endregion

        #region 方法
        void IBindingList.AddIndex(PropertyDescriptor property) { }

        Object IBindingList.AddNew()
        {
            T entity = (T)Factory.Create();
            base.Add(entity);
            OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, base.IndexOf(entity)));
            return entity;
        }

        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
            var list = InnerList as EntityList<T>;
            if (list == null || list.Count < 1) return;

            list.Sort(property.Name, direction == ListSortDirection.Descending);

            IsSorted = true;
            SortProperty = property;
            SortDirection = direction;

            OnListChanged(ResetEventArgs);
        }

        Int32 IBindingList.Find(PropertyDescriptor property, Object key)
        {
            var list = InnerList as EntityList<T>;
            if (list == null || list.Count < 1) return -1;

            return list.FindIndex(item => Object.Equals(item[property.Name], key));
        }

        void IBindingList.RemoveIndex(PropertyDescriptor property) { }

        void IBindingList.RemoveSort()
        {
            var list = InnerList as EntityList<T>;
            if (list == null || list.Count < 1) return;

            var fi = Factory.Fields[0];
            var isDesc = false;
            foreach (var item in Factory.Fields)
            {
                if (item.IsIdentity)
                {
                    fi = item;
                    isDesc = true;
                    break;
                }
                else if (item.PrimaryKey)
                {
                    fi = item;
                    isDesc = false;
                    break;
                }
            }
            list.Sort(Factory.Fields[0].Name, isDesc);

            IsSorted = false;
            SortProperty = null;
            SortDirection = ListSortDirection.Ascending;

            OnListChanged(ResetEventArgs);
        }
        #endregion
        #endregion

        #region IBindingListView接口
        void IBindingListView.ApplySort(ListSortDescriptionCollection sorts)
        {
            if (sorts == null || sorts.Count < 1) return;

            var list = InnerList as EntityList<T>;
            if (list == null || list.Count < 1) return;

            var ns = new List<String>();
            var ds = new List<Boolean>();
            foreach (ListSortDescription item in sorts)
            {
                ns.Add(item.PropertyDescriptor.Name);
                ds.Add(item.SortDirection == ListSortDirection.Descending);
            }

            list.Sort(ns.ToArray(), ds.ToArray());

            SortDescriptions = sorts;

            OnListChanged(ResetEventArgs);
        }

        String _Filter;
        String IBindingListView.Filter { get { return _Filter; } set { _Filter = value; } }

        void IBindingListView.RemoveFilter() { _Filter = ""; }

        ListSortDescriptionCollection _SortDescriptions;
        ListSortDescriptionCollection IBindingListView.SortDescriptions { get { return _SortDescriptions; } }
        /// <summary>获取当前应用于数据源的排序说明的集合。</summary>
        ListSortDescriptionCollection SortDescriptions
        {
            get { return _SortDescriptions; }
            set { if (_SortDescriptions != value) { _SortDescriptions = value; OnListChanged(ResetEventArgs); }; }
        }

        Boolean IBindingListView.SupportsAdvancedSorting { get { return true; } }

        Boolean IBindingListView.SupportsFiltering { get { return false; } }
        #endregion

        #region ICancelAddNew 成员
        void ICancelAddNew.CancelNew(Int32 itemIndex)
        {
            if (itemIndex < 0 || itemIndex >= Count) return;

            RemoveAt(itemIndex);
        }

        void ICancelAddNew.EndNew(Int32 itemIndex)
        {
            if (itemIndex < 0 || itemIndex >= Count) return;

            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, itemIndex));
        }
        #endregion

        #region 辅助函数
        /// <summary>真正的实体类型。有些场合为了需要会使用IEntity。</summary>
        Type EntityType
        {
            get
            {
                var type = typeof(T);
                if (!type.IsInterface) return type;

                if (Count > 0) return this[0].GetType();

                return type;
            }
        }

        /// <summary>实体操作者</summary>
        IEntityOperate Factory
        {
            get
            {
                var type = EntityType;
                if (type.IsInterface) return null;

                return EntityFactory.CreateOperate(type);
            }
        }
        #endregion
    }
}